package com.apexsoft.assets.base.handler;

import com.alibaba.fastjson.JSONObject;
import com.apexsoft.assets.base.exception.BizException;
import com.apexsoft.assets.base.exception.ValidException;
import com.apexsoft.assets.base.response.JSONResponse;
import com.apexsoft.assets.base.response.ValidResponse;
import com.apexsoft.live.exception.AuthException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created on 2018/3/5.
 *
 * @author Sury
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 所有异常报错
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public JSONResponse allExceptionHandler(HttpServletRequest request, Exception exception) throws Exception {
        JSONResponse resp = new JSONResponse(JSONResponse.CODE_FAIL, "系统异常，请稍候重试");
        LOG.error(exception.getMessage(), exception);
        return resp;
    }

    @ExceptionHandler(value = AuthException.class)
    @ResponseBody
    public JSONObject authExceptionHandler(HttpServletRequest request, AuthException exception) throws Exception {
        LOG.error(exception.getMessage(), exception);
        JSONObject resp = new JSONObject();
        resp.put("code", exception.getCode());
        resp.put("note", exception.getMessage());
        //resp.put("extInfo", exception.getExtInfo());
        return resp;
    }

    @ExceptionHandler(value = BizException.class)
    @ResponseBody
    public JSONResponse validExceptionHandler(HttpServletRequest request, BizException exception) throws Exception {
        return new JSONResponse(JSONResponse.CODE_FAIL, exception.getMessage());
    }

    @ExceptionHandler(value = ValidException.class)
    @ResponseBody
    public ValidResponse validExceptionHandler(HttpServletRequest request, ValidException exception) throws Exception {
        ValidResponse resp = new ValidResponse(JSONResponse.CODE_VALID, exception.getMessage(), exception.getError());
        return resp;
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public ValidResponse ConstraintViolationExceptionHandler(HttpServletRequest request, ConstraintViolationException exception) throws Exception {
        Set<ConstraintViolation<?>> result = exception.getConstraintViolations();
        Map<String, String> error = new HashMap<>();
        if (result.size() > 0) {
            for (ConstraintViolation<?> constraintViolation : result) {
                error.put(constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage());
            }
        }
        ValidResponse resp = new ValidResponse(JSONResponse.CODE_VALID, exception.getMessage(), error);
        return resp;
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseBody
    public ValidResponse MethodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException exception) throws Exception {
        List<ObjectError> result = exception.getBindingResult().getAllErrors();
        Map<String, String> error = new HashMap<>();
        if (result.size() > 0) {
            for (ObjectError item : result) {
                error.put(((FieldError)item).getField(), ((FieldError)item).getDefaultMessage());
            }
        }
        ValidResponse resp = new ValidResponse(JSONResponse.CODE_VALID, exception.getMessage(), error);
        return resp;
    }

    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public ValidResponse BindExceptionHandler(HttpServletRequest request, BindException exception) throws Exception {

        List<FieldError> result = exception.getFieldErrors();
        Map<String, String> error = new HashMap<>();
        if (result.size() > 0) {
            for (FieldError objectError : result) {
                error.put(objectError.getField(), objectError.getDefaultMessage());
            }
        }
        ValidResponse resp = new ValidResponse(JSONResponse.CODE_VALID, exception.getMessage(), error);
        return resp;
    }

}
